package com.gitee.sparta.core.cluster.netty.handler;

import com.gitee.sparta.core.bean.cluster.ClusterProtocol;
import com.gitee.sparta.core.cluster.AbstractClusterFollower;
import com.gitee.sparta.core.cluster.AbstractClusterLeader;
import com.gitee.sparta.core.cluster.ClusterCommonCode;
import com.gitee.sparta.core.cluster.balance.LoadBalance;
import com.gitee.sparta.core.cluster.strategy.Strategy;
import com.gitee.sparta.core.cluster.strategy.StrategyFactory;
import com.gitee.sparta.core.property.SpartaCoreProperties;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;

import java.io.IOException;

/**
 * <p>
 *
 * </p>
 *
 * @author zyred
 * @since v 0.0.2
 */
@Slf4j
@ChannelHandler.Sharable
public class FollowerProtocolHandler extends SimpleChannelInboundHandler<ClusterProtocol> {

    protected final ClusterCommonCode ccc;
    protected final RedissonClient client;
    protected final LoadBalance loadBalance;
    protected final AbstractClusterLeader leader;
    protected final SpartaCoreProperties properties;
    protected final AbstractClusterFollower follower;

    public FollowerProtocolHandler(RedissonClient client,
                                   SpartaCoreProperties properties,
                                   LoadBalance loadBalance,
                                   AbstractClusterLeader leader,
                                   ClusterCommonCode ccc,
                                   AbstractClusterFollower follower) {
        this.ccc = ccc;
        this.client = client;
        this.leader = leader;
        this.follower = follower;
        this.properties = properties;
        this.loadBalance = loadBalance;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ClusterProtocol cp) {
        Strategy strategy = StrategyFactory.getStrategy(cp.getCmd());
        strategy.handle(ctx, null, cp);
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        if (cause instanceof IOException) {
            log.error("[Sparta] Leader death, try promotion leader, cause : {}", cause.getMessage());
            this.ccc.promotionLeader(this.leader, this.follower);
        } else {
            log.error("[Sparta] Follower handler, exception caught", cause);
        }
    }
}
